package fag.core.game.space;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JFrame;

import fag.core.collision.Collision;
import fag.core.game.Camera;
import fag.core.game.StandardDoodad;
import fag.core.game.AbstractGame;
import fag.core.game.Scene;
import fag.core.game.Transformable.Referential;
import fag.core.game.test.arkanoid.Laser;
import fag.core.geometry.Rectangle2D;
import fag.core.geometry.Vector2D;

public class Space extends AbstractGame implements MouseMotionListener, MouseListener {	
	
	public static final int WIDTH = 400;
	public static final int HEIGHT = 800;
	
	public static final double FIRE_INTERVAL = 300.0;
	public static final double SPAWN_RATE = 500.0;
	
	private double fireTimer = 0;
	private double spawnTimer = 0;
	
	public static void main(String[] args) {
		
		Space space = new Space();
		space.start();
		
		JFrame frame = new JFrame();
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		frame.add(space.getCamera());
		frame.pack();
	}
	
	private SpaceHud hud = new SpaceHud();
	private SpaceScene scene = new SpaceScene();
	
	private Ship ship = new Ship();
	private List<Meteorite> meteorites = new ArrayList<Meteorite>();
	private List<Laser> lasers = new ArrayList<Laser>();
	
	private Vector2D mouseStamp = new Vector2D(WIDTH / 2, HEIGHT / 2);
	
	public Camera getCamera() {
		return hud;
	}
	
public Space() {
		
		addScene(scene);
		scene.addCamera(hud);
		scene.getQuadtree().setBounds(new Rectangle2D(0, 0, 400, 800));
		
		hud.setSize(WIDTH, HEIGHT);
		
		// Ship
		scene.addDoodad(ship);
		ship.translate(WIDTH / 2, 700, Referential.ABSOLUTE);
		
		// Meteorites
		for(int i = 0; i < 10; ++i) {
			Meteorite meteorite = new Meteorite();
			scene.addDoodad(meteorite);
			meteorites.add(meteorite);
			meteorite.translate(Math.random() * WIDTH, 50, Referential.ABSOLUTE);
		}
		
		// Ajout des listeners
		hud.addMouseListener(this);
		hud.addMouseMotionListener(this);
	}
	
	@Override
	public void step(double dt) {
		
		// Tirer un laser			
		if(fireTimer >= FIRE_INTERVAL) 
		{			
			fireTimer = 0;		
			Laser laser = new Laser();
			laser.translate(ship.getTranslationX() + 19 ,ship.getTranslationY(), Referential.ABSOLUTE);
			lasers.add(laser);
			scene.addDoodad(laser);
		}
			else
		{
				fireTimer += dt;
		}		
		
		// Collisions entre les meteorites
		for(int i = 0; i < meteorites.size() - 1; ++i) {
			for(int j = i + 1; j < meteorites.size(); ++j) {
				
				Meteorite a = meteorites.get(i);
				Meteorite b = meteorites.get(j);
				
				Collision collision = a.getHitbox().getCollision(b.getHitbox());
				
				if(collision.isColliding()) {
					meteorites.remove(a);
					meteorites.remove(b);
					scene.removeDoodad(a);
					scene.removeDoodad(b);
				}
			}	
		}
		
		// Collisions avec le ship
		for(int i = 0; i < meteorites.size() - 1; ++i) {
			Meteorite a = meteorites.get(i);
			
			Collision collision = a.getHitbox().getCollision(ship.getHitbox());
			
			if(collision.isColliding()) {
				meteorites.remove(a);	
				scene.removeDoodad(a);
			}
		}
		
		// Collisions entre les meteorites et les lasers
		for(int i = 0; i < meteorites.size() - 1; ++i) {
			for(int j = i + 1; j < lasers.size(); ++j) {
				
				Meteorite meteorite = meteorites.get(i);
				Laser laser = lasers.get(j);
				
				Collision collision = meteorite.getHitbox().getCollision(laser.getHitbox());
				
				if(collision.isColliding()) {
					meteorites.remove(meteorite);
					lasers.remove(laser);
					scene.removeDoodad(meteorite);
					scene.removeDoodad(laser);
				}
			}	
		}
		
	// Balles
		for(int i=0; i<meteorites.size(); i++) {
					
			Meteorite meteorite = meteorites.get(i);
			AffineTransform t = meteorite.getTransformation();
			double x = t.getTranslateX();
			double y = t.getTranslateY();
					
			// Collisions avec le bord de l'écran
			if(x < 14) {
				meteorite.translate(1, 0, Referential.ABSOLUTE);
				meteorite.bounce(new Vector2D(1, 0));
			}
			else if(x > WIDTH - 14) {
				meteorite.translate(-1, 0, Referential.ABSOLUTE);
				meteorite.bounce(new Vector2D(-1, 0));
			}
			
			if(y > HEIGHT) {
				meteorites.remove(meteorite);	
				scene.removeDoodad(meteorite);
			}
				meteorite.step(dt / 1000);		
			}
		
		// Lasers
		for(int i=0; i<lasers.size(); i++) {
			Laser laser = lasers.get(i);
			
			// Collisions avec le bord de l'écran
			if(laser.getTranslationY() < 0) {
				lasers.remove(laser);
				scene.removeDoodad(laser);
			}

			laser.step(dt / 1000);	
			}
		
			// Creer des meteorites
		if(spawnTimer>SPAWN_RATE) {
			spawnTimer = 0;
			Meteorite meteorite = new Meteorite();
			scene.addDoodad(meteorite);
			meteorites.add(meteorite);
			meteorite.translate(Math.random() * WIDTH, 50, Referential.ABSOLUTE);
		}
		else {
			spawnTimer += dt;
		}
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
	}

	@Override
	public void mouseEntered(MouseEvent e) {
	}

	@Override
	public void mouseExited(MouseEvent e) {
	}

	@Override
	public void mousePressed(MouseEvent e) {
	}

	@Override
	public void mouseReleased(MouseEvent e) {
	}

	@Override
	public void mouseDragged(MouseEvent e) {
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		double x = e.getX() - ship.getBounds().getWidth() / 2;
		ship.setTranslation(x, HEIGHT - 80);
		
	}
}
